// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

/// Basic information on a known component
export struct ComponentItem {
    name: string,
    index: int,
    defined-at: string,
    pretty-location: string,
    is-user-defined: bool,
    is-currently-shown: bool,
    is-exported: bool,
}

/// A `category` with a lost of `ComponentItem`s that belong into it.
///
/// Fiel url is either an empty string or a URL to some document
export struct ComponentListItem {
    category: string,
    file_url: string,
    components: [ComponentItem]
}

/// Some `Diagnostics` as raised by the compiler
export struct Diagnostics {
    level: string,
    message: string,
    url: string,
    line: int,
    column: int,
}

/// What kind of layout we are working with
export enum LayoutKind {
    None,
    Horizontal,
    Vertical,
    Grid,
}

/// A rectangular region that is selected
struct SelectionRectangle {
    x: length,
    y: length,
    width: length,
    height: length,
}

/// A `Selection`
export struct Selection {
    geometry: SelectionRectangle,
    layout-data: LayoutKind,
    is-primary: bool,
    is-moveable: bool,
    is-resizable: bool,
}

/// A mark showing where an element will show up when dropped into the current location
export struct DropMark {
    x1: length,
    y1: length,
    x2: length,
    y2: length,
}

/// A Range in a source
export struct Range {
    start: int,
    end: int,
}

export enum PropertyValueKind {
    boolean,
    brush,
    code,
    color,
    enum,
    float,
    integer,
    string,
}

/// Data about the property value for use in "simple" mode
export struct PropertyValue {
    value-bool: bool, // boolean
    is-translatable: bool, // string
    kind: PropertyValueKind,
    value-brush: brush, // brush, color
    value-float: float, // float
    value-int: int, // integer, enum/float (current index into visual_items)
    default-selection: int, // enum/float (default index into visual_items)
    value-string: string, // enum (name), string
    visual-items: [string], // enum (enum members), float (units)
    tr-context: string, // string
    tr-plural: string, // string
    tr-plural-expression: string, // string
    code: string, // ALWAYS, empty if property is not explicitly defined
}

/// Important Ranges in the property definition
///
/// The URL and version is the same as in the Element it belongs to
export struct PropertyDefinition {
    definition-range: Range,
    selection-range: Range,
    expression-range: Range,
    expression-value: string,
}

/// The Property Declaration
export struct PropertyDeclaration {
    source-path: string,
    source-version: int,
    range: Range,
}

/// Information on one Property
export struct PropertyInformation {
    name: string,
    type-name: string,
    declared-at: PropertyDeclaration,
    defined-at: PropertyDefinition,
    value: PropertyValue,
}

/// Information on one Property
export struct PropertyGroup {
    group-name: string,
    properties: [PropertyInformation],
}

/// Information on an Element a Property belongs to
export struct ElementInformation {
    id: string,
    type-name: string,
    source-uri: string,
    source-version: int,
    range: Range,

    properties: [PropertyGroup],
}

export global Api {
    // # Properties
    // ## General preview state:
    // experimental features are available
    in property <bool> experimental: false;
    // enable editing mode
    in property <bool> show-preview-ui: true;
    // Design-mode engaged!
    in-out property <bool> design-mode;
    // std-widgets are used (=> show style dropdown)
    in-out property <bool> uses-widgets;

    // ## Component Data for ComponentList:
    // All the components
    in property <[ComponentListItem]> known-components;
    // The component currently viewed
    out property <ComponentItem> visible-component;

    // ## Diagnostics and other Status messages
    // Compiler diagnostics
    in property <[Diagnostics]> diagnostics;
    // status message text
    in property <string> status-text;

    // ## Style:
    // All the known styles
    in property <[string]> known-styles;
    // The current style
    in-out property <string> current-style;
    // control, but command on macOS
    in-out property <string> control-key-name: "control";

    // ## Drawing Area
    // Borders around things
    in property <[Selection]> selections;
    in-out property <DropMark> drop-mark;
    // The actual preview
    in property <component-factory> preview-area;

    // set to true to resize
    in property <bool> resize-to-preferred-size: false;

    // ## Property Editor
    in property <ElementInformation> current-element;

    // # Callbacks

    // ## Style:
    callback style-changed();

    // ## Component life-cycle:

    // Create a new componnet
    callback add-new-component();

    // Add an existing component
    pure callback can-drop(/* component-index: */  int, /* x: */ length, /* y: */ length, /* on-drop-area: */ bool) -> bool;
    callback drop(/* component-index: */ int, /* x: */ length, /* y: */ length);

    callback rename-component(/* old-name: */ string, /* defined-at: */ string, /* new-name: */ string);

    callback selected-element-can-move-to(/* x: */ length, /* y: */ length, /* mouse-x: */ length, /* mouse-y: */ length) -> bool;
    callback selected-element-move(/* x: */ length, /* y: */ length, /* mouse-x: */ length, /* mouse-y: */ length);

    callback selected-element-resize(/* x: */ length, /* y: */ length, /* width: */ length, /* height: */ length);

    callback selected-element-delete();

    // ## Element selection:
    callback select-at(/* x: */ length, /* y: */ length, /* enter-component: */ bool);
    callback select-behind(/* x: */ length, /* y: */ length, /* enter-component: */ bool, /* reverse: */ bool);
    callback reselect();
    callback unselect();

    // ## Change Editor:

    // Show a conponent in the editor
    callback show-component(/* name: */ string, /* url: */ string);
    // Show a position consisting of `line` and `column` in a `file` in the editor
    callback show-document(/* file: */ string, /* line: */ int, /* column: */ int);
    // Show a position consisting of `line` and `column` in a `file` in the editor
    callback show-document-offset-range(/* url: */ string, /* start_offset: */ int, /* end_offset: */ int);

    // ## Drawing Area
    // Preview some other component
    callback show-preview-for(/* name: */ string, /* url: */ string);
    callback reload-preview();

    // ## Property Editor
    pure callback test-code-binding(/* element-url: */ string, /* element-version: */ int, /* element-offset: */ int, /* property-name: */ string, /* property-value: */ string) -> bool;
    pure callback test-string-binding(/* element-url: */ string, /* element-version: */ int, /* element-offset: */ int, /* property-name: */ string, /* value: */ string, /* is_translatable: */ bool, /* tr_context: */ string, /* tr_plural: */ string, /* tr_plural_expression: */ string) -> bool;
    callback set-code-binding(/* element-url: */ string, /* element-version: */ int, /* element-offset: */ int, /* property-name: */ string, /* property-value: */ string);
    callback set-color-binding(/* element-url: */ string, /* element-version: */ int, /* element-offset: */ int, /* property-name: */ string, /* property-value: */ color);
    callback set-string-binding(/* element-url: */ string, /* element-version: */ int, /* element-offset: */ int, /* property-name: */ string, /* value: */ string, /* is_translatable: */ bool, /* tr_context: */ string, /* tr_plural: */ string, /* tr_plural_exprression: */ string);
}
